package orm

import (
	"context"
	"strings"
)

// Selectable 是一个标记接口
// 代表的是查找的列或者聚合函数等
type Selectable interface {
	selectable()
}

type Selector[T any] struct {
	builder
	table   string
	where   []Predicate
	db      *DB
	columns []Selectable
}

//
//func (s *Selector[T]) SelectV1(cols  string) *Selector[T] {
//	s.columns = cols
//	return s
//}

//func (s *Selector[T]) Select(cols ...string) *Selector[T] {
//	s.columns = cols
//	return s
//}

func (s *Selector[T]) Select(cols ...Selectable) *Selector[T] {
	s.columns = cols
	return s
}

func NewSelector[T any](db *DB) *Selector[T] {
	return &Selector[T]{
		builder: builder{
			dialect: db.dialect,
			quoter:  db.dialect.quoter(),
			sb:      &strings.Builder{},
		},
		db: db,
	}
}

func (s *Selector[T]) Build() (*Query, error) {
	//var sb strings.Builder
	s.sb = &strings.Builder{} // 指针类型一定要初始化
	var err error
	s.model, err = s.db.r.Get(new(T)) // new(T) 生成T的指针
	if err != nil {
		return nil, err
	}
	sb := s.sb

	sb.WriteString("SELECT ")

	if err = s.buildColumns(); err != nil {
		return nil, err
	}
	sb.WriteString(` FROM `)

	if s.table == "" {
		sb.WriteByte('`')
		sb.WriteString(s.model.TableName)
		sb.WriteByte('`')
	} else {
		//segs := strings.Split(s.table, ".")
		//sb.WriteByte('`')
		sb.WriteString(s.table)
		//sb.WriteByte('`')
	}

	if len(s.where) > 0 {
		sb.WriteString(" WHERE ")
		if err := s.buildPredicates(s.where); err != nil {
			return nil, err
		}
	}

	sb.WriteByte(';')
	return &Query{
		SQL:  sb.String(),
		Args: s.args,
	}, nil
}

func (s *Selector[T]) buildColumns() error {
	if len(s.columns) == 0 {
		s.sb.WriteString("*")
		return nil
	}
	for i, col := range s.columns {
		// 在添加字段前添加 ,
		// 相对于在前一个col后加 ,
		if i > 0 {
			s.sb.WriteByte(',')
		}
		switch c := col.(type) {
		case Column:
			err := s.buildColumn(c)
			if err != nil {
				return err
			}
		case Aggregate:
			// 如果是聚合函数
			s.sb.WriteString(c.fn)
			s.sb.WriteByte('(')
			err := s.buildColumn(Column{name: c.arg})
			if err != nil {
				return err
			}
			s.sb.WriteByte(')')
			// 聚合函数的别名
			if c.alias != "" {
				s.sb.WriteString(" AS `")
				s.sb.WriteString(c.alias)
				s.sb.WriteByte('`')
			}
		case RawExpr:
			s.sb.WriteString(c.raw)
			//if len(c.args) > 0 {
			s.addArg(c.args...)
			//}
		}
	}
	return nil
}

//func (s *Selector[T]) buildExpression(raw Expression) error {
//	switch exp := raw.(type) {
//	case nil:
//	case Predicate:
//		// 处理p
//		_, ok := exp.left.(Predicate)
//		if ok {
//			s.sb.WriteByte('(')
//		}
//		if err := s.buildExpression(exp.left); err != nil {
//			return err
//		}
//		if ok {
//			s.sb.WriteByte(')')
//		}
//
//		s.sb.WriteByte(' ')
//		s.sb.WriteString(exp.op.String())
//		s.sb.WriteByte(' ')
//
//		_, ok = exp.right.(Predicate)
//		if ok {
//			s.sb.WriteByte('(')
//		}
//		if err := s.buildExpression(exp.right); err != nil {
//			return err
//		}
//		if ok {
//			s.sb.WriteByte(')')
//		}
//	case Column:
//		fd, ok := s.Model.fieldMap[exp.name]
//		// 传入了错误的字段
//		if !ok {
//			return errs.NewErrUnknownField(exp.name)
//		}
//		s.sb.WriteByte('`')
//		s.sb.WriteString(fd.colName)
//		s.sb.WriteByte('`')
//	//
//	case value:
//		s.sb.WriteByte('?')
//		s.addArg(exp.val)
//		//
//	default:
//		return errs.NewErrUnsupportedExpression(raw)
//	}
//	return nil
//}

//func (s *Selector[T]) addArg(val any) *Selector[T] {
//	if s.args == nil {
//		s.args = make([]any, 0, 8)
//	}
//	s.args = append(s.args, val)
//	return s
//}

func (s *Selector[T]) Where(ps ...Predicate) *Selector[T] {
	s.where = ps
	return s
}

//	func (s *Selector[T]) From(table string) *Selector[T] {
//		s.table = table
//		return s
//	}
func (s *Selector[T]) Table(table string) *Selector[T] {
	s.table = table
	return s
}

//func (s *Selector[T]) GetV1(ctx context.Context) (*T, error) {
//	q, err := s.Build()
//	if err != nil {
//		return nil, err
//	}
//
//	db := s.db.db
//	// 发起查询,并处理结果集
//	rows, err := db.QueryContext(ctx, q.SQL, q.Args...)
//	//_, err  = db.QueryContext(ctx, q.SQL, q.Args...)
//	// 查询错误
//	if err != nil {
//		return nil, err
//	}
//	if !rows.Next() {
//		return nil, ErrNoRows
//	}
//
//	tp := new(T)
//	var creator valuer.Creator
//	var val valuer.Value
//	err = val.SetColumns(rows)
//	return tp, err
//}

func (s *Selector[T]) Get(ctx context.Context) (*T, error) {
	q, err := s.Build()
	if err != nil {
		return nil, err
	}

	db := s.db.db
	// 发起查询,并处理结果集
	rows, err := db.QueryContext(ctx, q.SQL, q.Args...)
	//_, err  = db.QueryContext(ctx, q.SQL, q.Args...)
	// 查询错误
	if err != nil {
		return nil, err
	}
	if !rows.Next() {
		return nil, ErrNoRows
	}

	tp := new(T)
	val := s.db.creator(s.model, tp)
	err = val.SetColumns(rows)
	return tp, err
}

func (s *Selector[T]) GetMulti(ctx context.Context) ([]*T, error) {
	q, err := s.Build()
	if err != nil {
		return nil, err
	}

	db := s.db.db
	// 发起查询,并处理结果集
	rows, err := db.QueryContext(ctx, q.SQL, q.Args...)
	for rows.Next() {

	}
	return nil, nil
}
